using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Net;

namespace GSimp
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void cmdSubmit_Click(object sender, EventArgs e)
		{
			/************************************************/
			/*				Validate entry					*/
			/************************************************/




			/************************************************/
			/*				Generate Arrays					*/
			/************************************************/

			//define array of temps
			List<double> steplengths = new List<double>();
			createSLArray(steplengths);



			/************************************************/
			/*			Generate Input Files				*/
			/************************************************/

			List<string> paramfiles = new List<string>();
			createInputFiles(steplenths, paramfiles);




			/************************************************/
			/*					Grid Stuff					*/
			/************************************************/

			Mgsi.UdMgsi ud = new Mgsi.UdMgsi();
			ud.Url = mgsiUrl;

			//set the security policy to ignore the certificate error on bruce
			System.Net.ServicePointManager.CertificatePolicy = new MyPolicy();

			// Logging into the grid
			string auth = "";
			try
			{
				auth = ud.login(txtUsername.Text, txtPassword.Text);
			}
			catch (Exception exp)
			{
				MessageBox.Show("Error logging in: " + exp.Message + "\nPlease Try Again", "Error Logging In", MessageBoxButtons.OK, MessageBoxIcon.Error);
				txtUsername.Text = "";
				txtPassword.Text = "";
				return;
				//Environment.Exit(-1);
			}

			// Method used to set up the grid
			createGridInfo(paramfiles, ud, auth);
		}

		private void createSLArray(List<double> steplengths)
		{
			double slStart = double.Parse(txtSLStart.Text);
			double slStop = double.Parse(txtSLStop.Text);
			double slStep = double.Parse(txtSLStep.Text);
			double currentSl = slStart;
			while (currentSl <= slStop)
			{
				steplengths.Add(currentSl);
				currentSl = currentSl + slStep;
			}
		}

		private void createInputFiles(List<double> steplengths, List<string> paramfiles)
		{
			foreach (double sl in steplengths)
			{
				paramfiles.Add(writeFiles(sl));
			}// End StepLength
		}

		private string writeFiles(double sl)
		{
			string folder = txtInputFolder.Text + "\\" + txtJobName.Text;

			try
			{
				Directory.CreateDirectory(folder);
			}
			catch (Exception e)
			{
				MessageBox.Show("Error creating folder: " + e.Message);
				Environment.Exit(-1);
			}

			string name = createString(sl);
			StreamWriter sw = new StreamWriter(folder + "\\" + name);

			sw.WriteLine(txtSeed.Text);
			sw.WriteLine(sl);
			sw.WriteLine(txtNRuns.Text);
			sw.WriteLine(txtN.Text);
			sw.WriteLine(txtZmat.Text);
			sw.WriteLine(txtRaw.Text);

			sw.Close();

			return folder + "\\" + name;
		}

		private static string createString(double sl)
		{
			string slS = sl.ToString();
			slS = slS.Replace(".", "-");

			string s = "steplength" + slS + ".txt";

			return s;
		}

		private void createGridInfo(List<string> paramfiles, Mgsi.UdMgsi ud, string auth)
		{
			Mgsi.Application app = ud.getApplicationByName(auth, "Dev_SIMP");
			Mgsi.Program prog = ud.getProgramByName(auth, "Dev_SIMP");

			// Create job
			Mgsi.Job job = new Mgsi.Job();

			job.description = txtJobName.Text;
			job.state_id = 1;
			job.priority = 10;
			job.application_gid = app.application_gid;

			job.job_gid = ud.createJob(auth, job);

			// Create jobstep
			Mgsi.JobStep jobstep = new Mgsi.JobStep();
			jobstep.job_gid = job.job_gid;
			jobstep.state_id = 1;
			jobstep.program_gid = prog.program_gid;
			jobstep.num_results = 1;
			jobstep.max_errors = 3;
			jobstep.max_concurrent = 1;
			jobstep.wu_cpu_timeout = 36000;
			jobstep.wu_clock_timeout = 36000;

			jobstep.job_step_gid = ud.createJobStep(auth, jobstep);
			jobstep = ud.getJobStep(auth, jobstep.job_step_gid);

			// Create datasets
			Mgsi.DataSet dataset1 = new Mgsi.DataSet();
			dataset1.data_set_name = txtJobName.Text + "_ds1";
			dataset1.persistency = 50;
			dataset1.job_gid = job.job_gid;
			dataset1.job_step_gid = jobstep.job_step_gid;
			dataset1.data_set_gid = ud.createDataSet(auth, dataset1);

			Mgsi.DataSet dataset2 = new Mgsi.DataSet();
			dataset2.data_set_name = txtJobName.Text + "_ds2";
			dataset2.persistency = 50;
			dataset2.job_gid = job.job_gid;
			dataset2.job_step_gid = jobstep.job_step_gid;
			dataset2.data_set_gid = ud.createDataSet(auth, dataset2);

			// Create data items
			FileTransfer.FileTransfer ft = new FileTransfer.FileTransfer();

			string arguments = "-f -m\".$\" -n simp.tar simp.exe " + txtZmat.Text + " " + txtRaw.Text;

			// run buildpkg
			buildPkg(arguments);
			// simp.tar now exists

			FileTransfer.UploadData result = ft.uploadFile(auth, "simp.tar", fileServerUrl);

			Mgsi.Data simpdata = new Mgsi.Data();
			simpdata.data_set_gid = dataset1.data_set_gid;
			simpdata.index = 1;
			simpdata.file_hash = result.hash;
			simpdata.file_size = long.Parse(result.size);
			ud.createData(auth, simpdata);

			Mgsi.Data[] dataarray = new Mgsi.Data[paramfiles.Count];
			int counter = 0;

			foreach (string file in paramfiles)
			{
				arguments = "-f -m\".$\" -n datafile.tar \"" + file + "\"";
				//run buildpkg

				buildPkg(arguments);

				result = ft.uploadFile(auth, "datafile.tar", fileServerUrl);

				Mgsi.Data data = new Mgsi.Data();
				data.data_set_gid = dataset2.data_set_gid;
				data.index = counter + 1;
				data.file_hash = result.hash;
				data.file_size = long.Parse(result.size);

				dataarray[counter] = data;
				counter++;
			}

			ud.createDatas(auth, dataarray);

			string[] dsgid = new string[] { dataset1.data_set_gid, dataset2.data_set_gid };
			Mgsi.CreateWorkunitsFromDataSetsOptions options = new Mgsi.CreateWorkunitsFromDataSetsOptions();
			options.creation_mode = 0;

			ud.createWorkunitsFromDataSetsAsync(auth, jobstep.job_step_gid, dsgid, options);

			jobstep.state_id = 4;
			ud.updateJobStep(auth, jobstep);
		}

		private static void buildPkg(string arguments)
		{
			Process buildpkgProcess = new Process();
			buildpkgProcess.StartInfo.Arguments = arguments;
			buildpkgProcess.StartInfo.FileName = Application.StartupPath + @"\buildpkg.exe";
			buildpkgProcess.StartInfo.UseShellExecute = false;
			buildpkgProcess.StartInfo.RedirectStandardError = true;
			buildpkgProcess.StartInfo.RedirectStandardOutput = true;
			buildpkgProcess.StartInfo.CreateNoWindow = true;

			buildpkgProcess.Start();
			string error = buildpkgProcess.StandardError.ReadToEnd();
			string output = buildpkgProcess.StandardOutput.ReadToEnd();
			buildpkgProcess.WaitForExit();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
			{
				txtInputFolder.Text = folderBrowserDialog1.SelectedPath;
			}
		}

		private void button2_Click(object sender, EventArgs e)
		{
			openFileDialog1.InitialDirectory = Directory.GetCurrentDirectory();
			openFileDialog1.Title = "Open a .zmatrix file";
			openFileDialog1.Filter = "ZMatrix files (*.zmatrix)|*.zmatrix|All files (*.*)|*.*";
			openFileDialog1.FileName = ".zmatrix";

			if (openFileDialog1.ShowDialog() == DialogResult.OK)
			{
				txtZmat.Text = openFileDialog1.FileName;
			}
		}

		private void button3_Click(object sender, EventArgs e)
		{
			openFileDialog2.InitialDirectory = Directory.GetCurrentDirectory();
			openFileDialog2.Title = "Open a .txt file";
			openFileDialog2.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
			openFileDialog2.FileName = ".txt";

			if (openFileDialog2.ShowDialog() == DialogResult.OK)
			{
				txtRaw.Text = openFileDialog2.FileName;
			}
		}
				
	}

	class MyPolicy : ICertificatePolicy
	{
		public bool CheckValidationResult(ServicePoint srvPoint, System.Security.Cryptography.X509Certificates.X509Certificate certificate, WebRequest request, int problem)
		{
			return problem == 0
				|| problem == -2146762487  // CertUNTRUSTEDROOT
				|| problem == -2146762481; // CertCN_NO_MATCH
		}
	}
}